﻿using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Net.Http;
using System.Runtime.CompilerServices;
using System.Security.Cryptography;
using System.Threading.Tasks;
using System.Windows.Input;
using ZiChen.SoXunLeiPan.Common;
using ZiChen.SoXunLeiPan.Service;
using ZiChen.SoXunLeiPan.ViewModel.Result;

namespace ZiChen.SoXunLeiPan.ViewModel.View
{
    public class DetailsViewModel : INotifyPropertyChanged
    {
        private readonly IHttpService _httpService;
        private string _md5; // 存储传入的 MD5

        public DetailsViewModel(IHttpService httpService)
        {
            _httpService = httpService;
            LoadCommand = new Command<string>(async (md5) => await LoadData(md5));
            OpenLinkCommand = new Command(async () => await ExecuteOpenLink());
            ReportCommand = new Command(async () => await ExecuteReport());
            RetryCommand = new Command(async (param) => await LoadData(param as string));
            RelatedCommand = new Command(async (title) => await LoadRelated(title as string));
        }

        public string MD5
        {
            get => _md5;
            set
            {
                if (_md5 != value)
                {
                    _md5 = value;
                    OnPropertyChanged();
                    if (!string.IsNullOrEmpty(value))
                    {
                        LoadCommand.Execute(value); // 自动加载
                    }
                }
            }
        }
        
        #region 属性

        private PanUrlList _currentFile;
        public PanUrlList CurrentFile
        {
            get => _currentFile;
            set { _currentFile = value; OnPropertyChanged(); }
        }

        private bool _isSuccess;
        public bool IsSuccess
        {
            get => _isSuccess;
            set { _isSuccess = value; OnPropertyChanged(); }
        }

        private bool _isLoading;
        public bool IsLoading
        {
            get => _isLoading;
            set { _isLoading = value; OnPropertyChanged(); }
        }

        private string _errorMessage;
        public string ErrorMessage
        {
            get => _errorMessage;
            set { _errorMessage = value; OnPropertyChanged(); }
        }

        private int _errorType; // 0=正常, 1=网络错误, 2=无数据, 3=权限不足
        public int ErrorType
        {
            get => _errorType;
            set { _errorType = value; OnPropertyChanged(); }
        }
        //private List<PanUrlList> _relatedFiles;
        //public List<PanUrlList> RelatedFiles
        //{
        //    get => _relatedFiles;
        //    set { _currentFile = value; OnPropertyChanged(); }
        //}
        public ObservableCollection<PanUrlList> RelatedFiles { get; } = new();

        #endregion

        #region Commands

        public ICommand LoadCommand { get; }
        public ICommand OpenLinkCommand { get; }
        public ICommand ReportCommand { get; }
        public ICommand RetryCommand { get; }
        public ICommand RelatedCommand { get; set; }

        #endregion

        #region 方法实现

        private async Task ExecuteOpenLink()
        {
            if (string.IsNullOrEmpty(CurrentFile?.PanShare))
                return;

            try
            {
                await Launcher.Default.OpenAsync("https://pan.xunlei.com/s/"+CurrentFile.PanShare);
                var dict = new Dictionary<string, object>
                {
                    { "fid", MD5 },
                    { "timestamp", DateTimeOffset.UtcNow.ToUnixTimeSeconds() },
                    { "nonce", Guid.NewGuid().ToString() }
                };

                var secret = await SecureStorage.GetAsync("sign_secret");
                if (string.IsNullOrEmpty(secret))
                {
                    throw new InvalidOperationException("签名密钥未配置");
                }

                dict["sign"] = UrlSignTopRequest.Sign(dict, secret);

                var queryString = string.Join("&", dict.Select(kv => $"{kv.Key}={Uri.EscapeDataString(kv.Value.ToString())}"));
                var url = $"/api/updata?{queryString}";

                var result = await _httpService.PostAsync<UnifyResult<PanUrlList>, bool>(url, null, "ApiClient");
            }
            catch (Exception ex)
            {
                await Application.Current.MainPage.DisplayAlert("打开失败", "无法打开链接：" + ex.Message, "确定");
            }
        }

        private async Task ExecuteReport()
        {
            var result = await Application.Current.MainPage.DisplayAlert(
                "举报资源",
                "确定要举报此资源吗？我们将尽快处理。",
                "举报",
                "取消");

            if (result)
            {
                var dict = new Dictionary<string, object>
                {
                    { "fid", MD5 },
                    { "timestamp", DateTimeOffset.UtcNow.ToUnixTimeSeconds() },
                    { "nonce", Guid.NewGuid().ToString() }
                };

                var secret = await SecureStorage.GetAsync("sign_secret");
                if (string.IsNullOrEmpty(secret))
                {
                    throw new InvalidOperationException("签名密钥未配置");
                }

                dict["sign"] = UrlSignTopRequest.Sign(dict, secret);

                var queryString = string.Join("&", dict.Select(kv => $"{kv.Key}={Uri.EscapeDataString(kv.Value.ToString())}"));
                var url = $"/api/report?{queryString}";

                var response = await _httpService.PostAsync<string, UnifyResult>(url, null, "ApiClient");
                if(response.Code == ResultCode.Success)
                {
                    await Application.Current.MainPage.DisplayAlert("举报成功", "感谢您的反馈，我们会尽快处理。", "确定");
                }
                else
                {
                    await Application.Current.MainPage.DisplayAlert("举报失败", response?.Msg.ToString(), "确定");
                }
            }
        }

        public async Task LoadData(string md5)
        {
            MD5 = md5; // 同步属性

            if (string.IsNullOrEmpty(md5))
            {
                ErrorType = 2;
                ErrorMessage = "文件不存在或已被删除";
                CurrentFile = null;
                return;
            }
            IsSuccess = false;
            IsLoading = true;
            ErrorMessage = null;
            ErrorType = 0;
            CurrentFile = null;
            RelatedFiles.Clear();

            try
            {
                var dict = new Dictionary<string, object>
                {
                    { "fid", md5 },
                    { "timestamp", DateTimeOffset.UtcNow.ToUnixTimeSeconds() },
                    { "nonce", Guid.NewGuid().ToString() }
                };

                var secret = await SecureStorage.GetAsync("sign_secret");
                if (string.IsNullOrEmpty(secret))
                {
                    throw new InvalidOperationException("签名密钥未配置");
                }

                dict["sign"] = UrlSignTopRequest.Sign(dict, secret);

                var queryString = string.Join("&", dict.Select(kv => $"{kv.Key}={Uri.EscapeDataString(kv.Value.ToString())}"));
                var url = $"/api/getshare?{queryString}";

                var result = await _httpService.GetAsync<UnifyResult<PanUrlList>>(url, "ApiClient");

                if (result?.Code == ResultCode.Success && result.Data != null)
                {
                    CurrentFile = result.Data;
                    IsSuccess = true;
                    await Task.Delay(500);
                    RelatedCommand.Execute(CurrentFile.elseTitle);
                }
                else
                {
                    IsLoading = false;
                    ErrorType = 2;
                    ErrorMessage = result?.Msg.ToString() ?? "文件不存在";
                }
            }
            catch (TaskCanceledException)
            {
                ErrorType = 1;
                ErrorMessage = "请求超时，请检查网络连接";
            }
            catch (HttpRequestException)
            {
                ErrorType = 1;
                ErrorMessage = "网络连接失败，请检查网络设置";
            }
            catch (UnauthorizedAccessException)
            {
                ErrorType = 3;
                ErrorMessage = "您没有权限查看此文件";
            }
            catch (Exception ex)
            {
                ErrorType = 4;
                ErrorMessage = "加载失败：" + ex.Message;
            }
            finally
            {
                IsLoading = false;
            }
        }

        public async Task LoadRelated(string title)
        {
            var dict = new Dictionary<string, object>
                {
                    { "timestamp", DateTimeOffset.UtcNow.ToUnixTimeSeconds() },
                    { "nonce", Guid.NewGuid().ToString() }
                };

            var secret = await SecureStorage.GetAsync("sign_secret");
            if (string.IsNullOrEmpty(secret))
            {
                throw new InvalidOperationException("签名密钥未配置");
            }
            var requst = new             
            {
                keyword = string.IsNullOrEmpty(title) ? "" : (title.Length > 30 ? title[..30] : title),
                page = 1,
                pageSize = 10
            };
            dict["keyword"] = requst.keyword;
            dict["page"] = requst.page;
            dict["pageSize"] = requst.pageSize;
            dict["sign"] = UrlSignTopRequest.Sign(dict, secret);

            var queryString = string.Join("&", dict.Select(kv => $"{kv.Key}={Uri.EscapeDataString(kv.Value.ToString())}"));
            var url = $"/api/Related?{queryString}";

            var result = await _httpService.PostAsync<object,UnifyResult<List<PanUrlList>>>(url, requst, "ApiClient");

            if (result?.Code == ResultCode.Success && result.Data != null)
            {
                RelatedFiles.Clear();
                foreach (var item in result.Data)
                {
                    RelatedFiles.Add(item);
                }
            }
            else
            {
                ErrorType = 2;
                ErrorMessage = result?.Msg.ToString() ?? "文件不存在";
            }
        }
        #endregion

        #region INotifyPropertyChanged

        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        #endregion
    }
}